package com.ruoyi.web.controller.common;

import com.ruoyi.utils.SimpleResult;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@RestController
@RequestMapping("/download")
public class DownLoadController {
    // 文件地址
    @Value("${ruoyi.profile}")
    private String profile;

    /**
     * @param urlList 需要下载的视频的地址
     * @param response 响应体
     * @param request 请求体
     * @return {@code SimpleResult}
     */
    @PostMapping("/bulk")
    public SimpleResult bulkDownload(@RequestBody String[] urlList, HttpServletResponse response, HttpServletRequest request) {
        File profilezip = new File(profile);
        if(!profilezip.exists()) {
            profilezip.mkdirs(); // 创建目录, 防止目录不存在
        }
        // 前提工作, 删除目标目录中的非目录文件
        File[] zipList = profilezip.listFiles();
        for (File zipFile : zipList) {
            if(!zipFile.isDirectory()) {
                zipFile.delete();
            }
        }
        System.out.println("----------清理文件完成----------");
        // 1. 把需要下载的文件复制到临时文件保存地址中
        int complete = 0; // 已经复制完成的数量
        for (String url : urlList) {
            url = url.substring(8); // 去掉下载文件的开头的 profile\
            File sourceFile = new File(profile + url); // 源文件
            File destinationFile = new File(profile + "/" + sourceFile.getName()); // 目标文件
            boolean result = copyFile(sourceFile, destinationFile);
            if(result) {
                complete ++;
            }
        }
        System.out.println("----------拷贝文件完成----------");
        // 2. 把临时文件目录压缩成一个压缩包
        boolean zipResult = zipFile(profile);
        if(zipResult) {
            System.out.println("----------压缩文件完成----------");
            String message = "期望下载" + urlList.length + "个, 成功下载" + complete + "个";
            // 压缩完成之后返回下载路径(vue使用)
            return SimpleResult.success("/profile/zip.zip", message);
        }
        return SimpleResult.error("压缩文件失败");
    }

    // 复制文件
    public boolean copyFile(File sourceFile, File destinationFile) {
        // 源文件不存在直接返回false
        if(!sourceFile.exists()) {
            return false;
        }
        try {
            FileInputStream inputStream = new FileInputStream(sourceFile);
            FileOutputStream outputStream = new FileOutputStream(destinationFile);
            byte[] bytes = new byte[2048];
            int read = inputStream.read(bytes);
            while(read != -1) {
                outputStream.write(bytes);
                read = inputStream.read(bytes);
            }
            inputStream.close();
            outputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    // 创建压缩文件, 并压缩指定目录文件
    public boolean zipFile(String path) {
        File sourceFile = new File(path);
        File zipFile = new File(path + "/" + "zip.zip");
        try {
            ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
            File[] sourceFiles = sourceFile.listFiles();
            for (File file : sourceFiles) {
                // 不是文件夹以及不是压缩文件
                if(!file.isDirectory() && !file.getName().endsWith(".zip")) {
                    FileInputStream fileInputStream = new FileInputStream(file);
                    ZipEntry zipEntry = new ZipEntry(file.getName()); // 压缩包中的文件对象
                    zipOut.putNextEntry(zipEntry); // 添加下一个对象
                    byte[] bytes = new byte[2048];
                    int read = fileInputStream.read(bytes);
                    while (read != -1) {
                        zipOut.write(bytes);
                        read = fileInputStream.read(bytes);
                    }
                    zipOut.closeEntry(); // 关闭对象
                    fileInputStream.close();
                }
            }
            zipOut.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return false;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
}
